package com.sinosoft.web.common;

import com.sinosoft.hydra.logging.LogModules;
import cn.com.sinux.spring.commons.SystemConfig;
import cn.com.sinux.spring.exception.BusinessException;
import cn.com.sinux.spring.exception.RequestFailure;
import cn.com.sinux.spring.utils.JsonUtils;
import cn.com.sinux.spring.utils.RequestUtils;
import cn.com.sinux.spring.utils.ResourceUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.springframework.web.servlet.view.UrlBasedViewResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Locale;

/**
 * Created with IntelliJ IDEA.
 * User: Administrator
 * Date: 14-3-11
 * Time: 下午12:49
 * To change this template use File | Settings | File Templates.
 */
public class TilesMappingExceptionResolver extends
        SimpleMappingExceptionResolver {

    private static final Logger logger = LoggerFactory.getLogger(LogModules.STD_LOGGER);

    private UrlBasedViewResolver urlBasedViewResolver;

    public void setUrlBasedViewResolver(UrlBasedViewResolver urlBasedViewResolver) {
        this.urlBasedViewResolver = urlBasedViewResolver;
    }

    private static final String AJAX_TYPE_JSON = "json";

    public ModelAndView resolveException(HttpServletRequest request,
                                         HttpServletResponse response, Object handler, Exception ex) {

        logger.debug("exception is {}", ex.getMessage());
        ex.printStackTrace();

        if (RequestUtils.isAjaxRequest(request)) {
            Enumeration ajaxParams = request.getParameterNames();
            String ajaxParam = null;
            while (ajaxParams != null && ajaxParams.hasMoreElements()) {
                Object obj = ajaxParams.nextElement();
                if (obj != null && obj instanceof String && StringUtils.equalsIgnoreCase("ajaxtype", (String) obj)) {
                    ajaxParam = (String) obj;
                    break;
                }
            }
            String ajaxType = ajaxParam == null ? AJAX_TYPE_JSON : request.getParameter(ajaxParam);
            ajaxType = ajaxType == null ? AJAX_TYPE_JSON : ajaxType;
            if (AJAX_TYPE_JSON.equals(ajaxType)) {
                return resolveAjaxException(request, response, ex);
            }
        }
        return super.resolveException(request, response, handler, ex);
    }

    private ModelAndView resolveAjaxException(HttpServletRequest request, HttpServletResponse response, Exception ex) {
        String exceptionMessage = StringUtils.trimToEmpty(ex.getMessage());
        RequestFailure ajaxRequestFailure = new RequestFailure();
        if (logger.isDebugEnabled()) {
            ajaxRequestFailure.setCode(ex.getMessage());
            ajaxRequestFailure.setError(true);
        }
        String level = SystemConfig.getProperty("app.tip.level", "CLIENT");
        if ("CLIENT".equals(level) && !(ex instanceof BusinessException)) {
            exceptionMessage = "system.server.error";
        }
        ajaxRequestFailure.setMsg(ResourceUtils.getMsg(exceptionMessage, request.getLocale()));
        response.setContentType("application/json;charset=utf-8");
        printHTML(response, JsonUtils.toString(ajaxRequestFailure));
        return new ModelAndView();
    }

    private void printHTML(HttpServletResponse response, String htmlToPrint) {
        try {
            PrintWriter printWriter = response.getWriter();
            printWriter.print(htmlToPrint);
            printWriter.close();
        } catch (IOException e) {
            logger.debug("An io exception ocurred when getting the printWriter.");
        }
    }


    protected ModelAndView getModelAndView(String viewName, Exception ex, HttpServletRequest request) {
        ModelAndView mv = new ModelAndView(viewName);
        if (logger.isDebugEnabled()) {
            logger.debug("Exposing Exception as model attribute '" + DEFAULT_EXCEPTION_ATTRIBUTE + "'");
        }
        mv.addObject(DEFAULT_EXCEPTION_ATTRIBUTE, ex);
        ViewResolver vr = this.urlBasedViewResolver;

        if (vr == null) {
            mv.addObject("error", true);
            mv.addObject("msg", ResourceUtils.getMsg(ex.getMessage(), request.getLocale()));
            return mv;
        }

        Locale locale = request.getLocale();
        View v = null;
        try {
            v = vr.resolveViewName(mv.getViewName(), locale);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        if (v != null) {
            logger.error(ex.getMessage(), ex);
            ex.printStackTrace();
            mv.addObject("error", true);
            mv.addObject("msg", ResourceUtils.getMsg(ex.getMessage(), request.getLocale()));
            mv.setView(v);
        }
        return mv;
    }
}
